# coding=utf-8
# -*- coding: UTF-8 -*-
#
# This file is part of the kernelstudio package.
#
# (c) 2014-2025 zlin <admin@kernelstudio.com>
#
# For the full copyright and license information, please view the LICENSE file
# that was distributed with this source code.
import hashlib
import json
import logging
import mimetypes
import os
import re
import typing as t
from urllib.parse import urlparse

from flask import request
from werkzeug.utils import secure_filename

from ksai.persistence.storage.attachment import Attachment
from ksai.services.dify_upload_file import DifyUploadFileService
from ksai.utils.paths import get_project_storage_path

logger = logging.getLogger(__name__)


def parse_request_attachments() -> list[Attachment]:
    try:
        files = json.loads(request.form.get('files', []))
    except Exception as e:
        raise ValueError(str(e))

    attachments = []

    if len(files) > 0:
        for f in files:
            if 'url' not in f:
                continue
            parsed_url = urlparse(f['url'])
            path = parsed_url.path
            # 解析dify文件地址格式
            uuid_pattern = r'/files/([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})/'
            match = re.search(uuid_pattern, path)
            if not match:
                continue
            uuid_str = match.group(1)
            try:
                file = DifyUploadFileService.find_one_by_uuid(uuid_str)
            except Exception as e:
                logger.error("Could not find attachment for uuid {}: {}".format(uuid_str, e))
                continue
            filepath = get_project_storage_path(file.key)
            if file and os.path.isfile(filepath):
                with open(filepath, 'rb') as fd:
                    content = fd.read()
                attachments.append(Attachment(
                    uuid=uuid_str,
                    mime=file.mime_type,
                    suffix=file.extension,
                    filename=file.key.split('/')[-1],
                    size=file.size,
                    original_name=file.name,
                    filepath='/' + str(file.key).lstrip('/'),
                    url=file.source_url,
                    sign=file.hash,
                    content=content,
                ))

    return attachments


def parse_ocr_request_options(defaults: dict[str, t.Any] = None) -> dict[str, t.Any]:
    options = None
    try:
        options_str = request.form.get("options", "{}")
        if options_str is None:
            options_str = request.args.get("options", "{}")
        if options_str is None:
            options_str = request.get_json().get("options", "{}")
        options = json.loads(options_str)
    except Exception as e:
        logger.error("Can't parse options: %s", e)
    if options is None:
        options = {}
    if defaults is not None:
        options.update(defaults)

    return options


def parse_request_attachment() -> Attachment:
    if 'file' in request.files:
        file = request.files['file']
        file_bytes = file.read()
        filename = secure_filename(file.filename)
        mime_type, encoding = mimetypes.guess_type(filename)
        sign = hashlib.md5(file_bytes).hexdigest()
        f = Attachment(
            filename=filename,
            content=file_bytes,
            size=len(file_bytes),
            sign=sign,
            suffix='.' + filename.split('.')[-1],
            mime=mime_type
        )
        file.close()
        return f

    data = request.get_json()

    if 'file' in data:
        file = data.get('file')
        filename = data.get('filename')

        filepath = get_project_storage_path(file)
        if os.path.isfile(filepath):
            if filename is None:
                filename = filepath.split('/')[-1]
            file_bytes = open(filepath, 'rb').read()
            filename = secure_filename(filename)
            suffix = '.' + filename.split('.')[-1]
            mime_type, encoding = mimetypes.guess_type(filename)
            return Attachment(
                filename=filename,
                filepath=filepath,
                content=file_bytes,
                size=len(file_bytes),
                sign=hashlib.md5(file_bytes).hexdigest(),
                suffix=suffix,
                mime=mime_type
            )

    raise ValueError("File required.")
